/*****************************************************************************
 * (C) Copyright 2015 Atech-Automotive
 * FILE NAME:    app_bcan.c
 * DESCRIPTION:  
 * DATE BEGUN:   
 * BY:           
 * PRODUCT NAME: 
 * APPLICATION:  
 * TARGET H/W:   
 * DOC REF:
 *****************************************************************************
 */
/* #include */
#include <string.h>
#include "app_can.h"
#include "app_can_Itf.h"
/*
    version
*/
//const VERSION_TYPE_S u8_canAppLibVersion = 
//{
//    //v1.3
//    1,
//    3,
//   //year,month,date
//    17,
//    11,
//    25
//};


static BOOL b_canEnableTx = TRUE;
static BOOL b_canEnableRx = TRUE;

static UINT8 u8_canTxErrCount = 0;

static BOOL b_canRxKeepFlg = FALSE;/*if msg be received in 10ms, it will be set*/
static UINT8 u8_canRxKeepTimer = 0;

/* static function prototypes */
static void app_canRxMsgs(void);
static void app_canUpdateTxMsgs(void);
static void app_canCheckTimeout(void);
static void app_canCheckTimeOutError(CAN_RX_MSG_S* p_s_canMsg);
static void app_canCycTxMsgs(void);
static void app_canMoniterErr(void);


//VERSION_TYPE_S const * app_canGetVersion( void ) 
//{
//    return &u8_canAppLibVersion;
//}

#define CAN_INIT
/******************************************************************************/
/**
 * Function Name: app_bcanSysInit
 * Description: none
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *                            draft                     
 *  06/08/2015           standardize form               martin.Zhang
 ******************************************************************************/
void app_canSysInit(void)
{
    (void)app_canItfCanInit(); 
}

#define CAN_HANDLER
/******************************************************************************/
/**
 * Function Name: app_canHandler10ms
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *                            draft                     
 *  06/08/2015           standardize form               martin.Zhang
 ******************************************************************************/
void Comm_can1_vHandler10ms(void)
{
    app_canRxMsgs();
    app_canItfCanHandler10ms();
    app_canCheckTimeout();
    app_canUpdateTxMsgs();
    app_canCycTxMsgs(); 
    app_canMoniterErr();
}

#define CAN_TX_MSG
/*
 * TxMsgs*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
 */
/******************************************************************************/
/**
 * Function Name: app_canUpdateTxMsgs
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canUpdateTxMsgs(void)
{
    app_canItfUpdataTxMsgs();   
}

/******************************************************************************/
/**
 * Function Name: app_bcanTxMsgs
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canCycTxMsgs(void)
{
    static BOOL     b_canEnableTxOld = TRUE;    
    CAN_TX_MSG_S **ptr;
    UINT8    u8_index = 0;
    
    ptr = p_s_canCycTxTable;
    u8_index = 0;
/* ban transmit CAN message*/
    if (FALSE == b_canEnableTx)
    {
        if(b_canEnableTxOld)/*enable -> disable*/
        {
            b_canEnableTxOld = b_canEnableTx;

            /*reset msg some parameter*/
            while( (*ptr)->Id != 0 )
            {
                (*ptr)->CycleTimer = u8_index;//(*ptr)->CycleTime;
                (*ptr)->Trigger    = FALSE;

                ptr++;
                u8_index++;
            }
        }
        return;
    }
    else
    {
        b_canEnableTxOld = b_canEnableTx;
    }
    
/*allow transmit CAN messages*/
    ptr = p_s_canCycTxTable;
    while( (*ptr)->Id != 0 )
    {
        if((*ptr)->Enable)
        {
            /*cycle send*/
            if((*ptr)->SendType == CAN_CYCLE)
            {
                if((*ptr)->CycleTimer)
                {
                    (*ptr)->CycleTimer--;
                }
                if((*ptr)->CycleTimer == 0)/*time end*/
                {
                    /*reset cycle timer*/
                    (*ptr)->CycleTimer = (*ptr)->CycleTime;

                    /*send msg*/
                    if (app_canItfSendFrame((*ptr)->Id,0x00,(*ptr)->Length,(*ptr)->Data) == FALSE)
                    {
                        (*ptr)->CycleTimer= 1;        /*rz retry in the next 10ms time slot */ 
                        if(u8_canTxErrCount<0xFF)
                        {
                            u8_canTxErrCount ++;
                        }                        
                    }
                    else
                    {
                        /* transmit success */
                        u8_canTxErrCount = 0;
                    }    
                }
            }
            /*event send*/
            else if((*ptr)->SendType == CAN_EVENT)
            {
                if((*ptr)->Trigger)
                {
                    /*send msg*/
                    if (app_canItfSendFrame((*ptr)->Id,0x00,(*ptr)->Length,(*ptr)->Data) == FALSE)
                    {
                        if(u8_canTxErrCount<0xFF)
                        {
                            u8_canTxErrCount ++;
                        }  
                    }
                    else
                    {
                        /* transmit success */
                        (*ptr)->Trigger = FALSE;
                        u8_canTxErrCount = 0;
                    } 
                }
            }
            /*cycle and event send*/
            else if((*ptr)->SendType == CAN_CE)
            {
                if((*ptr)->CycleTimer >0)
                {
                    (*ptr)->CycleTimer--;
                }
                if((*ptr)->CycleTimer == 0)/*time end*/
                {
                    /*reset cycle timer*/
                    (*ptr)->CycleTimer = (*ptr)->CycleTime;

                    /*send msg*/
                    if (app_canItfSendFrame((*ptr)->Id,0x00,(*ptr)->Length,(*ptr)->Data) == FALSE)
                    {
                        (*ptr)->CycleTimer= 1;        /*rz retry in the next 10ms time slot */ 
                        if(u8_canTxErrCount<0xFF)
                        {
                            u8_canTxErrCount ++;
                        }  
                    }
                    else
                    {
                        /* transmit success */
                        u8_canTxErrCount = 0;
                    }    
                }
				
				if((*ptr)->Trigger)
                {
                    /*send msg*/
                    if (app_canItfSendFrame((*ptr)->Id,0x00,(*ptr)->Length,(*ptr)->Data) == FALSE)
                    {
                        if(u8_canTxErrCount<0xFF)
                        {
                            u8_canTxErrCount ++;
                        }  
                    }
                    else
                    {
                        /* transmit success */
                        (*ptr)->Trigger = FALSE;
                        u8_canTxErrCount = 0;
                    } 
                }
            }
        }
        ptr++;
    }

}

#define CAN_RX_MSG
/*
 * RxMsgs*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
 */
 /******************************************************************************/
/**
 * Function Name: app_bcanRxMsgs
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canRxMsgs(void)
{
    UINT32 u32_id;
    UINT8 u8_length;
    UINT8 p_u8_data[8];
    UINT8 u8_canRdCounter = u8_canReadMsgsOnceMax;  
    CAN_RX_MSG_S **ptr;     

    /* Update can message*/
    while (u8_canRdCounter && (app_canItfGetRxMessageCount() > 0))//if CANRxbuffer have new message, we can get the new message
    {    
        u8_canRdCounter--;     /* make sure we don't stay here forever */		        
		
        app_canItfGetMessage(&u32_id, &u8_length, p_u8_data);

        if(b_canEnableRx)
        {
            /*========================= OSEK NWM ======================================*/
            if(c_b_canOsekNwmEnable && ((u32_id & c_u32_osekNmRxIdMask) == c_u32_osekNmRxBase))/*OSEK msg*/
            {
                app_canItfCanMsgOsek_Rx(u32_id,u8_length,p_u8_data);
            }
            /*========================= NORMAL NWM ======================================*/
            else
            {
				ptr = p_s_canRxTable;
				
                while((*ptr)->Id != 0)
                {
                    if((*ptr)->Id == u32_id)
                    {
                        (*ptr)->Length = u8_length;
						(void)memcpy((*ptr)->LastData,(*ptr)->Data, u8_length);//dy
                        (void)memcpy((*ptr)->Data, p_u8_data, u8_length);
                        (*ptr)->Error = FALSE;
                        (*ptr)->CycleTimer = (*ptr)->CycleTimeOut;
                        (*ptr)->UpdataState = TRUE; 
                        app_canItfRecMsg(u32_id,u8_length,p_u8_data);
                        break;
                    }
                    ptr++;
                }
            }          
        }
        else/*for UDS communication control*/
        {
            ptr = p_s_canRxTable;
            while((*ptr)->Id != 0)
            {
                if((*ptr)->Type == CAN_DIAG)
                {
                    if((*ptr)->Id == u32_id)
                    {
                        (*ptr)->Length = u8_length;
                        (void)memcpy((*ptr)->Data, p_u8_data, u8_length);
                        (*ptr)->Error = FALSE;
                        (*ptr)->CycleTimer = (*ptr)->CycleTimeOut;
                        (*ptr)->UpdataState = TRUE;    
                        app_canItfRecMsg(u32_id,u8_length,p_u8_data);
                        break;
                    }
                }                
                ptr++;
            }
        }
    }
}

/******************************************************************************/
/**
 * Function Name: app_canCheckTimeout
 * Description: check can msg timeout
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/30/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canCheckTimeout(void)
{
    CAN_RX_MSG_S **ptr;        

     /*
     * check timeout
     */
    if(app_canItfGetIGN())
    {
        ptr = p_s_canRxTable;
        while((*ptr)->Id != 0)
        {   
            if((*ptr)->SendType != CAN_EVENT)
            {
                app_canCheckTimeOutError(*ptr);
            }            
            ptr++;
        }

/*
* just for CAN GW.
* Other module,please keep the default form 
*/
#if( CAN_RX_FAST == TRUE )
        ptr = p_s_canFastRxTable;
        while((*ptr)->Id != 0)
        {   
            if((*ptr)->SendType != CAN_EVENT)
            {
                app_canCheckTimeOutError(*ptr);
            }            
            ptr++;
        }
#endif        
    }
    else
    {
        ptr = p_s_canRxTable;
        while((*ptr)->Id != 0)
        {
            if((*ptr)->PowerType == POWER_30 && (*ptr)->SendType != CAN_EVENT)
            {
                app_canCheckTimeOutError(*ptr);
            }
            ptr++;
        }                

/*
* just for CAN GW.
* Other module,please keep the default form 
*/
#if( CAN_RX_FAST == TRUE )
        ptr = p_s_canFastRxTable;
        while((*ptr)->Id != 0)
        {
            if((*ptr)->PowerType == POWER_30 && (*ptr)->SendType != CAN_EVENT)
            {
                app_canCheckTimeOutError(*ptr);
            }
            ptr++;
        } 
#endif        
    }
}
    

/*
 *  can error deal *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
 */
/******************************************************************************/
/**
 * Function Name: app_canCheckTimeOutError
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canCheckTimeOutError(CAN_RX_MSG_S* p_s_canMsg)
{
    if(p_s_canMsg->CycleTimer)
    {
        p_s_canMsg->CycleTimer--;            
    }
    else
    {
        p_s_canMsg->Error = TRUE;
        //data recover to inital value
        (void)memcpy(p_s_canMsg->Data,
                     p_s_canMsg->InitData,
                     p_s_canMsg->Length);
    }
}

/******************************************************************************/
/**
 * Function Name: app_canGetError
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
BOOL app_canGetError(CAN_RX_MSG_S s_canMsg)
{
      return s_canMsg.Error;
}

/******************************************************************************/
/**
 * Function Name: app_canClearError
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
static void app_canClearError(CAN_RX_MSG_S* p_s_canMsg)
{
    p_s_canMsg->Error = FALSE;
    p_s_canMsg->CycleTimer= p_s_canMsg->CycleTimeOut;
}

/******************************************************************************/
/**
 * Function Name: app_canClearAllError
 * Description: none
 *
 * Param:   none
 * Return:  none
 * _____________________________________________________________________________
 *     Date             Changes Description                Author
 *  06/08/2015                draft                     martin.Zhang
 ******************************************************************************/
void app_canClearAllError(void)
{
    CAN_RX_MSG_S **ptr;
    ptr = p_s_canRxTable;
    while((*ptr)->Id != 0)
    {
        app_canClearError(*ptr);
        ptr++;
    }

/*
 * just for CAN GW.
 * Other module,please keep the default form 
*/
#if( CAN_RX_FAST == TRUE )
    ptr = p_s_canFastRxTable;
    while((*ptr)->Id != 0)
    {
        app_canClearError(*ptr);
        ptr++;
    }
#endif    
}


/*interface*/
void app_canTxCtrl(BOOL CMD)
{
    if(CMD)
    {
        b_canEnableTx = TRUE;
    }
    else
    {
        b_canEnableTx = FALSE;
    }    
}

BOOL app_canGetTxCtrl( void )
{
    return b_canEnableTx;
}

void app_canRxCtrl(BOOL CMD)
{
    if(CMD)
    {
        b_canEnableRx = TRUE;
    }
    else
    {
        b_canEnableRx = FALSE;
    }
    
}

static void app_canMoniterErr(void)
{
    return;
	//if(!lin1_bool_rd(CX62_PEPS_LIN1_RX_SlaveBootLoaderEnable_l_signal_bool_Handle)) return;
    /*
     *  IGN_ON,    moniter STB state
    */
    if(app_canItfGetIGN())
    {
        if(app_canItfGetSTB() == FALSE)
        {
            app_canItfEnableSTB();
        }            
    }

    /*
     * BUS_ OFF,    moniter STB state
    */
    if (app_canItfGetCanBusOffState())
    {
        if(app_canItfGetSTB() == FALSE)
        {
            app_canItfEnableSTB();
        }
    }

}


#define CAN_FAST_DEAL
/*
 * just for CAN GW.
 * Other module,please keep the default form 
*/
#if( CAN_RX_FAST == TRUE )
static void app_canRxMsgsFast(void)
{
    UINT32 u32_id;
    UINT8 u8_length;
    UINT8 p_u8_data[8];
    UINT8 u8_canRdCounter = u8_canReadFastMsgsOnceMax;  
    CAN_RX_MSG_S **ptr;     

    /* Update can message*/
    while (u8_canRdCounter && (app_canItfGetFastRxMessageCount() > 0))//if CANRxbuffer have new message, we can get the new message
    {    
        u8_canRdCounter--;     /* make sure we don't stay here forever */		        
		
        app_canItfGetFastMessage(&u32_id, &u8_length, p_u8_data);

        if(b_canEnableRx)
        {
				ptr = p_s_canFastRxTable;
				
                while((*ptr)->Id != 0)
                {
                    if((*ptr)->Id == u32_id)
                    {
                        (*ptr)->Length = u8_length;
                        (void)memcpy((*ptr)->Data, p_u8_data, u8_length);
                        (*ptr)->Error = FALSE;
                        (*ptr)->CycleTimer = (*ptr)->CycleTimeOut;
                        (*ptr)->UpdataState = TRUE; 
                        app_canItfRecFastMsg(u32_id,u8_length,p_u8_data);
                        break;
                    }
                    ptr++;
                }         
        }
        else/*for UDS communication control*/
        {

        }
    }

}

void app_canHandlerRt(void)
{ 
    app_canRxMsgsFast();
    app_canItfCanHandlerRt();     
}
#endif


/*****************************************************************************
** End File
*****************************************************************************/

